{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a520a022",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | default_exp _cli"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3f5a4483",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | export\n",
    "\n",
    "import asyncio\n",
    "import multiprocessing\n",
    "from typing import *\n",
    "\n",
    "import typer\n",
    "\n",
    "from fastkafka import _cli_docs, _cli_testing\n",
    "from fastkafka._components.logger import get_logger\n",
    "from fastkafka._server import run_fastkafka_server"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "347594e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import platform\n",
    "import time\n",
    "\n",
    "from typer.testing import CliRunner\n",
    "\n",
    "from fastkafka._components.logger import suppress_timestamps\n",
    "from fastkafka._components.test_dependencies import generate_app_in_tmp\n",
    "from fastkafka._server import terminate_asyncio_process\n",
    "from fastkafka.testing import ApacheKafkaBroker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6babc3b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | notest\n",
    "\n",
    "# allows async calls in notebooks\n",
    "\n",
    "import nest_asyncio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "44a4e2d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | notest\n",
    "\n",
    "nest_asyncio.apply()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae202a18",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | export\n",
    "\n",
    "logger = get_logger(__name__, level=20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5ec0fba",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[INFO] __main__: ok\n"
     ]
    }
   ],
   "source": [
    "suppress_timestamps()\n",
    "logger = get_logger(__name__, level=20)\n",
    "logger.info(\"ok\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a2bfc60c",
   "metadata": {},
   "outputs": [],
   "source": [
    "runner = CliRunner()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf57b082",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | export\n",
    "\n",
    "_app = typer.Typer(help=\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b4830f45",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | export\n",
    "\n",
    "\n",
    "@_app.command(\n",
    "    help=\"Runs Fast Kafka API application\",\n",
    ")\n",
    "def run(\n",
    "    num_workers: int = typer.Option(\n",
    "        multiprocessing.cpu_count(),\n",
    "        help=\"Number of FastKafka instances to run, defaults to number of CPU cores.\",\n",
    "    ),\n",
    "    app: str = typer.Argument(\n",
    "        ...,\n",
    "        help=\"input in the form of 'path:app', where **path** is the path to a python file and **app** is an object of type **FastKafka**.\",\n",
    "    ),\n",
    "    kafka_broker: str = typer.Option(\n",
    "        \"localhost\",\n",
    "        help=\"kafka_broker, one of the keys of the kafka_brokers dictionary passed in the constructor of FastaKafka class.\",\n",
    "    ),\n",
    ") -> None:\n",
    "    \"\"\"\n",
    "    Runs FastKafka application.\n",
    "\n",
    "    Args:\n",
    "        num_workers (int): Number of FastKafka instances to run, defaults to the number of CPU cores.\n",
    "        app (str): Input in the form of 'path:app', where **path** is the path to a python file and **app** is an object of type **FastKafka**.\n",
    "        kafka_broker (str): Kafka broker, one of the keys of the kafka_brokers dictionary passed in the constructor of FastKafka class.\n",
    "\n",
    "    Raises:\n",
    "        typer.Exit: If there is an unexpected internal error.\n",
    "    \"\"\"\n",
    "    try:\n",
    "        asyncio.run(\n",
    "            run_fastkafka_server(\n",
    "                num_workers=num_workers, app=app, kafka_broker=kafka_broker\n",
    "            )\n",
    "        )\n",
    "    except Exception as e:\n",
    "        typer.secho(f\"Unexpected internal error: {e}\", err=True, fg=typer.colors.RED)\n",
    "        raise typer.Exit(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3328d21",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | notest\n",
    "\n",
    "! nbdev_export"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f47cd927",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "<span style=\"font-weight: bold\"> </span><span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">Usage: </span><span style=\"font-weight: bold\">run [OPTIONS] APP                                                                                          </span>\n",
       "<span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m                                                                                                                   \u001b[0m\n",
       "\u001b[1m \u001b[0m\u001b[1;33mUsage: \u001b[0m\u001b[1mrun [OPTIONS] APP\u001b[0m\u001b[1m                                                                                         \u001b[0m\u001b[1m \u001b[0m\n",
       "\u001b[1m                                                                                                                   \u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"> Runs Fast Kafka API application                                                                                   \n",
       "                                                                                                                   \n",
       "</pre>\n"
      ],
      "text/plain": [
       " Runs Fast Kafka API application                                                                                   \n",
       "                                                                                                                   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #800000; text-decoration-color: #800000\">*</span>    app      <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">TEXT</span>  input in the form of 'path:app', where **path** is the path to a python file and **app** is <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     an object of type **FastKafka**.                                                            <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">[default: None]                                                                            </span> <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     <span style=\"color: #bf7f7f; text-decoration-color: #bf7f7f\">[required]                                                                                 </span> <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2m╭─\u001b[0m\u001b[2m Arguments \u001b[0m\u001b[2m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[31m*\u001b[0m    app      \u001b[1;33mTEXT\u001b[0m  input in the form of 'path:app', where **path** is the path to a python file and **app** is \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     an object of type **FastKafka**.                                                            \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     \u001b[2m[default: None]                                                                            \u001b[0m \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     \u001b[2;31m[required]                                                                                 \u001b[0m \u001b[2m│\u001b[0m\n",
       "\u001b[2m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--num-workers</span>               <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">INTEGER</span>  Number of FastKafka instances to run, defaults to number of CPU cores.     <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                                      <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">[default: 4]                                                          </span>     <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--kafka-broker</span>              <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">TEXT   </span>  kafka_broker, one of the keys of the kafka_brokers dictionary passed in    <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                                      the constructor of FastaKafka class.                                       <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                                      <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">[default: localhost]                                                      </span> <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--install-completion</span>        <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">       </span>  Install completion for the current shell.                                  <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--show-completion</span>           <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">       </span>  Show completion for the current shell, to copy it or customize the         <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                                      installation.                                                              <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--help</span>                      <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">       </span>  Show this message and exit.                                                <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2m╭─\u001b[0m\u001b[2m Options \u001b[0m\u001b[2m──────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-num\u001b[0m\u001b[1;36m-workers\u001b[0m               \u001b[1;33mINTEGER\u001b[0m  Number of FastKafka instances to run, defaults to number of CPU cores.     \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                                      \u001b[2m[default: 4]                                                          \u001b[0m     \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-kafka\u001b[0m\u001b[1;36m-broker\u001b[0m              \u001b[1;33mTEXT   \u001b[0m  kafka_broker, one of the keys of the kafka_brokers dictionary passed in    \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                                      the constructor of FastaKafka class.                                       \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                                      \u001b[2m[default: localhost]                                                      \u001b[0m \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-install\u001b[0m\u001b[1;36m-completion\u001b[0m        \u001b[1;33m       \u001b[0m  Install completion for the current shell.                                  \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-show\u001b[0m\u001b[1;36m-completion\u001b[0m           \u001b[1;33m       \u001b[0m  Show completion for the current shell, to copy it or customize the         \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                                      installation.                                                              \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-help\u001b[0m                      \u001b[1;33m       \u001b[0m  Show this message and exit.                                                \u001b[2m│\u001b[0m\n",
       "\u001b[2m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "result = runner.invoke(_app, [\"run\", \"--help\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "942f780d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | export\n",
    "\n",
    "\n",
    "_app.add_typer(_cli_docs._docs_app, name=\"docs\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5fc53859",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | notest\n",
    "\n",
    "! nbdev_export"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "557347c7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "<span style=\"font-weight: bold\"> </span><span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">Usage: </span><span style=\"font-weight: bold\">root docs install_deps [OPTIONS]                                                                           </span>\n",
       "<span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m                                                                                                                   \u001b[0m\n",
       "\u001b[1m \u001b[0m\u001b[1;33mUsage: \u001b[0m\u001b[1mroot docs install_deps [OPTIONS]\u001b[0m\u001b[1m                                                                          \u001b[0m\u001b[1m \u001b[0m\n",
       "\u001b[1m                                                                                                                   \u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"> Installs dependencies for FastKafka documentation generation                                                      \n",
       "                                                                                                                   \n",
       "</pre>\n"
      ],
      "text/plain": [
       " Installs dependencies for FastKafka documentation generation                                                      \n",
       "                                                                                                                   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--help</span>          Show this message and exit.                                                                     <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2m╭─\u001b[0m\u001b[2m Options \u001b[0m\u001b[2m──────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-help\u001b[0m          Show this message and exit.                                                                     \u001b[2m│\u001b[0m\n",
       "\u001b[2m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "result = runner.invoke(_app, [\"docs\", \"install_deps\", \"--help\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ed5d781",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[INFO] fastkafka._components.docs_dependencies: AsyncAPI generator installed\n"
     ]
    }
   ],
   "source": [
    "result = runner.invoke(_app, [\"docs\", \"install_deps\"])\n",
    "assert result.exit_code == 0, f\"exit_code = {result.exit_code}, output = {result.stdout}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1cc8e68a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "<span style=\"font-weight: bold\"> </span><span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">Usage: </span><span style=\"font-weight: bold\">root docs generate [OPTIONS] APP                                                                           </span>\n",
       "<span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m                                                                                                                   \u001b[0m\n",
       "\u001b[1m \u001b[0m\u001b[1;33mUsage: \u001b[0m\u001b[1mroot docs generate [OPTIONS] APP\u001b[0m\u001b[1m                                                                          \u001b[0m\u001b[1m \u001b[0m\n",
       "\u001b[1m                                                                                                                   \u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"> Generates documentation for a FastKafka application                                                               \n",
       "                                                                                                                   \n",
       "</pre>\n"
      ],
      "text/plain": [
       " Generates documentation for a FastKafka application                                                               \n",
       "                                                                                                                   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #800000; text-decoration-color: #800000\">*</span>    app      <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">TEXT</span>  input in the form of 'path:app', where **path** is the path to a python file and **app** is <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     an object of type **FastKafka**.                                                            <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">[default: None]                                                                            </span> <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     <span style=\"color: #bf7f7f; text-decoration-color: #bf7f7f\">[required]                                                                                 </span> <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2m╭─\u001b[0m\u001b[2m Arguments \u001b[0m\u001b[2m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[31m*\u001b[0m    app      \u001b[1;33mTEXT\u001b[0m  input in the form of 'path:app', where **path** is the path to a python file and **app** is \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     an object of type **FastKafka**.                                                            \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     \u001b[2m[default: None]                                                                            \u001b[0m \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     \u001b[2;31m[required]                                                                                 \u001b[0m \u001b[2m│\u001b[0m\n",
       "\u001b[2m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--root-path</span>        <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">TEXT</span>  root path under which documentation will be created; default is current directory      <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--help</span>             <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">    </span>  Show this message and exit.                                                            <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2m╭─\u001b[0m\u001b[2m Options \u001b[0m\u001b[2m──────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-root\u001b[0m\u001b[1;36m-path\u001b[0m        \u001b[1;33mTEXT\u001b[0m  root path under which documentation will be created; default is current directory      \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-help\u001b[0m             \u001b[1;33m    \u001b[0m  Show this message and exit.                                                            \u001b[2m│\u001b[0m\n",
       "\u001b[2m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "result = runner.invoke(_app, [\"docs\", \"generate\", \"--help\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a759342",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[INFO] fastkafka._components.asyncapi: Old async specifications at '/tmp/tmp7598io9j/asyncapi/spec/asyncapi.yml' does not exist.\n",
      "[INFO] fastkafka._components.asyncapi: New async specifications generated at: '/tmp/tmp7598io9j/asyncapi/spec/asyncapi.yml'\n",
      "[INFO] fastkafka._components.asyncapi: Async docs generated at 'asyncapi/docs'\n",
      "[INFO] fastkafka._components.asyncapi: Output of '$ npx -y -p @asyncapi/generator ag asyncapi/spec/asyncapi.yml @asyncapi/html-template -o asyncapi/docs --force-write'\u001b[32m\n",
      "\n",
      "Done! ✨\u001b[0m\n",
      "\u001b[33mCheck out your shiny new generated files at \u001b[0m\u001b[35m/tmp/tmp7598io9j/asyncapi/docs\u001b[0m\u001b[33m.\u001b[0m\n",
      "\n",
      "\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "with generate_app_in_tmp() as import_str:\n",
    "    result = runner.invoke(_app, [\"docs\", \"generate\", import_str])\n",
    "    typer.echo(result.output)\n",
    "    assert result.exit_code == 0, f\"exit_code = {result.exit_code}, output = {result.output}\"\n",
    "\n",
    "    result = runner.invoke(_app, [\"docs\", \"generate\", import_str])\n",
    "    typer.echo(result.output)\n",
    "    assert result.exit_code == 0, f\"exit_code = {result.exit_code}, output = {result.output}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e81b95fe",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "<span style=\"font-weight: bold\"> </span><span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">Usage: </span><span style=\"font-weight: bold\">root docs serve [OPTIONS] APP                                                                              </span>\n",
       "<span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m                                                                                                                   \u001b[0m\n",
       "\u001b[1m \u001b[0m\u001b[1;33mUsage: \u001b[0m\u001b[1mroot docs serve [OPTIONS] APP\u001b[0m\u001b[1m                                                                             \u001b[0m\u001b[1m \u001b[0m\n",
       "\u001b[1m                                                                                                                   \u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"> Generates and serves documentation for a FastKafka application                                                    \n",
       "                                                                                                                   \n",
       "</pre>\n"
      ],
      "text/plain": [
       " Generates and serves documentation for a FastKafka application                                                    \n",
       "                                                                                                                   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #800000; text-decoration-color: #800000\">*</span>    app      <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">TEXT</span>  input in the form of 'path:app', where **path** is the path to a python file and **app** is <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     an object of type **FastKafka**.                                                            <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">[default: None]                                                                            </span> <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>                     <span style=\"color: #bf7f7f; text-decoration-color: #bf7f7f\">[required]                                                                                 </span> <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2m╭─\u001b[0m\u001b[2m Arguments \u001b[0m\u001b[2m────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[31m*\u001b[0m    app      \u001b[1;33mTEXT\u001b[0m  input in the form of 'path:app', where **path** is the path to a python file and **app** is \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     an object of type **FastKafka**.                                                            \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     \u001b[2m[default: None]                                                                            \u001b[0m \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m                     \u001b[2;31m[required]                                                                                 \u001b[0m \u001b[2m│\u001b[0m\n",
       "\u001b[2m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--root-path</span>        <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">TEXT   </span>  root path under which documentation will be created; default is current directory   <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--bind</span>             <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">TEXT   </span>  Some info <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">[default: 127.0.0.1]</span>                                                      <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--port</span>             <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">INTEGER</span>  Some info <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">[default: 8000]</span>                                                           <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--help</span>             <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">       </span>  Show this message and exit.                                                         <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2m╭─\u001b[0m\u001b[2m Options \u001b[0m\u001b[2m──────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-root\u001b[0m\u001b[1;36m-path\u001b[0m        \u001b[1;33mTEXT   \u001b[0m  root path under which documentation will be created; default is current directory   \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-bind\u001b[0m             \u001b[1;33mTEXT   \u001b[0m  Some info \u001b[2m[default: 127.0.0.1]\u001b[0m                                                      \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-port\u001b[0m             \u001b[1;33mINTEGER\u001b[0m  Some info \u001b[2m[default: 8000]\u001b[0m                                                           \u001b[2m│\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-help\u001b[0m             \u001b[1;33m       \u001b[0m  Show this message and exit.                                                         \u001b[2m│\u001b[0m\n",
       "\u001b[2m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "result = runner.invoke(_app, [\"docs\", \"serve\", \"--help\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d2a20790",
   "metadata": {},
   "outputs": [],
   "source": [
    "with generate_app_in_tmp() as app:\n",
    "    proc = await asyncio.create_subprocess_exec(\n",
    "        \"fastkafka\",\n",
    "        \"docs\",\n",
    "        \"serve\",\n",
    "        \"--port=48000\",\n",
    "        app,\n",
    "        stdout=asyncio.subprocess.PIPE,\n",
    "    )\n",
    "    time.sleep(120)\n",
    "    await terminate_asyncio_process(proc)\n",
    "    outputs, errs = await proc.communicate()\n",
    "    expected_returncode = 15 if platform.system() == \"Windows\" else 0\n",
    "    assert proc.returncode == expected_returncode, f\"output = {outputs.decode('utf-8')}\\n exit code = {proc.returncode}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f1ec310",
   "metadata": {},
   "outputs": [],
   "source": [
    "# | export\n",
    "\n",
    "\n",
    "_app.add_typer(_cli_testing._testing_app, name=\"testing\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "447b94f1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "<span style=\"font-weight: bold\"> </span><span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">Usage: </span><span style=\"font-weight: bold\">root testing install_deps [OPTIONS]                                                                        </span>\n",
       "<span style=\"font-weight: bold\">                                                                                                                   </span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1m                                                                                                                   \u001b[0m\n",
       "\u001b[1m \u001b[0m\u001b[1;33mUsage: \u001b[0m\u001b[1mroot testing install_deps [OPTIONS]\u001b[0m\u001b[1m                                                                       \u001b[0m\u001b[1m \u001b[0m\n",
       "\u001b[1m                                                                                                                   \u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"> Installs dependencies for FastKafka app testing                                                                   \n",
       "                                                                                                                   \n",
       "</pre>\n"
      ],
      "text/plain": [
       " Installs dependencies for FastKafka app testing                                                                   \n",
       "                                                                                                                   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">--help</span>          Show this message and exit.                                                                     <span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">│</span>\n",
       "<span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[2m╭─\u001b[0m\u001b[2m Options \u001b[0m\u001b[2m──────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n",
       "\u001b[2m│\u001b[0m \u001b[1;36m-\u001b[0m\u001b[1;36m-help\u001b[0m          Show this message and exit.                                                                     \u001b[2m│\u001b[0m\n",
       "\u001b[2m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "result = runner.invoke(_app, [\"testing\", \"install_deps\", \"--help\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5a0b955",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "3f1cd496ac314d81aa61242a62545e93",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/833975 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "result = runner.invoke(_app, [\"testing\", \"install_deps\"])\n",
    "assert result.exit_code == 0, f\"exit_code = {result.exit_code}, output = {result.output}\""
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
